/* eslint-disable react-hooks/exhaustive-deps */

import { useCallback, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';

import { useEditor, useNode } from '@craftjs/core';

import { DeleteIcon } from '../Icons';
import styles from './index.module.less';

export const RenderNode = ({ render, editAreaRef }: any) => {
  const { id } = useNode();
  const { actions, query, isActive } = useEditor((_, query) => ({
    isActive: query.getEvent('selected').contains(id),
  }));

  const { isHover, dom, name, deletable } = useNode((node) => ({
    isHover: node.events.hovered,
    dom: node.dom,
    name: node.data.props.label || node.data.displayName,
    moveable: query.node(node.id).isDraggable(),
    deletable: query.node(node.id).isDeletable(),
    parent: node.data.parent,
    props: node.data.props,
  }));
  const currentRef = useRef<HTMLDivElement>();

  useEffect(() => {
    if (dom) {
      if (isActive || isHover) {
        dom.classList.add('component-selected');
      } else {
        dom.classList.remove('component-selected');
      }
    }
  }, [dom, isHover, isActive]);

  const getPos = useCallback((dom: HTMLElement) => {
    const { top, left, bottom } = dom
      ? dom.getBoundingClientRect()
      : { top: 0, left: 0, bottom: 0 };
    return {
      top: `${(top > 0 ? top : bottom) - 3}px`,
      left: `${left - 3}px`,
    };
  }, []);

  const scroll = useCallback(() => {
    const { current: currentDOM } = currentRef;

    if (!currentDOM) return;
    const { top, left } = getPos(dom as any);
    currentDOM.style.top = top;
    currentDOM.style.left = left;

    // 当编辑区域出现滚动条时，隐藏超过编辑区顶部的指示器
    const { top: editAreaTop = 0 } =
      editAreaRef?.current?.getBoundingClientRect() || {};

    currentDOM.style.display = editAreaTop - parseFloat(top) > 10 ? 'none' : '';
  }, [dom, getPos]);

  useEffect(() => {
    editAreaRef?.current?.addEventListener('scroll', scroll);
    return () => {
      editAreaRef?.current?.removeEventListener('scroll', scroll);
    };
  }, [scroll]);

  useEffect(() => {
    const parentScrollContainer = document.body;
    if (parentScrollContainer) {
      parentScrollContainer.addEventListener('scroll', scroll);
    }

    return () => {
      if (parentScrollContainer) {
        parentScrollContainer.removeEventListener('scroll', scroll);
      }
    };
  }, [scroll]);

  return (
    <>
      {isHover || isActive
        ? ReactDOM.createPortal(
            <div
              ref={currentRef as any}
              className={styles.indicator}
              style={{
                left: getPos(dom as any).left,
                top: getPos(dom as any).top,
                zIndex: 9,
              }}
            >
              <h2>{name}</h2>

              {deletable && (
                <a
                  className={styles.btn}
                  style={{ cursor: 'pointer' }}
                  onClick={(e) => {
                    e.stopPropagation();
                    actions.delete(id);
                  }}
                >
                  <DeleteIcon />
                </a>
              )}
            </div>,
            document.body
          )
        : null}
      {render}
    </>
  );
};
